package com.mall.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mall.db.api.*;
import com.mall.dto.UmsAdminLoginParam;
import com.mall.exception.ConsumerException;
import com.mall.pageResult.PageResult;
import com.mall.pojo.*;
import com.mall.utils.AppJwtUtil;
import com.mall.utils.Result;
import com.mall.utils.ThreadLocalUtil;
import io.jsonwebtoken.Claims;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class AdminService {

    @DubboReference
    private AdminApi adminApi;

    @DubboReference
    private UmsAdminRoleRelationApi adminRoleRelationApi;

    @DubboReference
    private UmsRoleApi roleApi;

    @DubboReference
    private UmsMenuApi menuApi;

    @DubboReference
    private UmsRoleMenuRelationApi roleMenuRelationApi;

    /**
     * 登录
     *
     * @param umsAdminLoginParam
     * @return
     */
    public Map<String, String> login(UmsAdminLoginParam umsAdminLoginParam) {
        //1.拿到登录的用户名和密码
        String username = umsAdminLoginParam.getUsername();
        String password = umsAdminLoginParam.getPassword();

        //2.根据用户名查询用户,判断用户是否为空
        UmsAdmin umsAdmin = adminApi.findAdminByUsername(username);
        if (ObjectUtil.isNull(umsAdmin)) {
            //用户为空
            throw new ConsumerException("用户名或密码错误");
        }
        //3.判断账户是否被冻结
        if (umsAdmin.getStatus() != 1) {
            throw new ConsumerException("账号已禁用");
        }
        //4.比对密码
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (!passwordEncoder.matches(password, umsAdmin.getPassword())) {
            //比对失败
            throw new ConsumerException("密码不正确");
        }
        //5.生成token
        String token = AppJwtUtil.getToken(umsAdmin.getId());
        //6.修改最后登陆时间
        umsAdmin.setLoginTime(new Date(System.currentTimeMillis()));
        adminApi.update(umsAdmin);

        //组装返回结果数据
        Map<String, String> result = new HashMap<>();
        result.put("token", token);
        result.put("tokenHead", "Bearer ");
        return result;
    }

    /**
     * 解析token
     *
     * @return
     */
    public Long parseToken(String token) {
        Claims claims = AppJwtUtil.getClaimsBody(token);
        //判断token是否过期
        int i = AppJwtUtil.verifyToken(claims);
        if (i == 1 || i == 2) {
            throw new ConsumerException("token已过期");
        }
        return Convert.toLong(claims.get("id"));
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    public Map<String, Object> info() {
        //返回结果数据
        Map<String, Object> result = new HashMap<>();
        //1.当前管理员id
        Long id = ThreadLocalUtil.getId();
        //2.根据当前管理员id查询角色id
        UmsAdminRoleRelation relation = adminRoleRelationApi.findByAdmin(id);
        Long roleId = relation.getRoleId();
        //3.根据角色id查询角色名
        UmsRole role = roleApi.findByRole(roleId);
        String name = role.getName();
        //4.判读用户是否为超管
        List<String> roles = new ArrayList<>();
        List<UmsMenu> menus = new ArrayList<>();
        if (StrUtil.equals(name, "超级管理员")) {
            //超管获取所有管理角色名
            List<UmsRole> roleList = roleApi.findAll();
            roles = roleList.stream().map(role1 -> {
                return role1.getName();
            }).collect(Collectors.toList());
            //超管获取所有菜单对象
            menus = menuApi.findAll();
        } else {
            //普通管理员角色名
            roles.add(name);
            //普通管理员菜单
            //通过角色id查询菜单id数组
            List<UmsRoleMenuRelation> relations = roleMenuRelationApi.findByRole(roleId);
            List<Long> menuIds = CollUtil.getFieldValues(relations, "menuId", Long.class);
            //通过菜单id查询菜单对象
            menus = menuApi.findByIds(menuIds);
        }
        //5.查询当前管理员信息
        UmsAdmin admin = adminApi.findById(id);

        result.put("icon", admin.getIcon());
        result.put("username", admin.getUsername());
        result.put("roles", roles);
        result.put("menus", menus);

        return result;
    }

    /**
     * 根据用户名或姓名分页获取用户列表
     *
     * @param pageNum
     * @param pageSize
     * @param keyword
     * @return
     */
    public PageResult<UmsAdmin> list(Integer pageNum, Integer pageSize, String keyword) {
        //根据用户名或姓名获取用户列表分页信息
        Page<UmsAdmin> page = adminApi.list(pageNum, pageSize, keyword);
        //组装返回结果数据
        PageResult<UmsAdmin> result = new PageResult<>();
        result.setPageNum(pageNum);
        result.setPageSize(pageSize);
        result.setList(page.getRecords());
        result.setTotal(Convert.toInt(page.getTotal()));
        result.setTotalPage(Convert.toInt(page.getPages()));
        return result;
    }

    /**
     * 用户注册
     *
     * @param umsAdminParam
     * @return
     */
    public UmsAdmin register(UmsAdmin umsAdminParam) {
        //判断邮箱是否合法 xx@xx
        String regEx1 = "^([\\w]+)@([\\w]+)$";
        Pattern p;
        Matcher m;
        p = Pattern.compile(regEx1);
        m = p.matcher(umsAdminParam.getEmail());
        if (!m.matches()) {
            throw new ConsumerException("email不是一个合法的电子邮件地址");
        }
        //密码加密，设置创建时间
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        umsAdminParam.setPassword(encoder.encode(umsAdminParam.getPassword()));
        umsAdminParam.setCreateTime(new Date(System.currentTimeMillis()));
        //注册
        Long id = adminApi.register(umsAdminParam);
        umsAdminParam.setId(id);
        return umsAdminParam;
    }

    /**
     * 删除指定用户信息
     *
     * @param id
     * @return
     */
    public Integer delete(Integer id) {
        Integer count = adminApi.delete(id);
        return count;
    }

    /**
     * 修改指定用户信息
     *
     * @param id
     * @param admin
     * @return
     */
    public Integer update(Integer id, UmsAdmin admin) {
        //判断邮箱是否合法 xx@xx
        String regEx1 = "^[\\w+]+@[\\w+]+\\.(com|net|org|edu|mil|tv|biz|info)$";
        Pattern p;
        Matcher m;
        p = Pattern.compile(regEx1);
        m = p.matcher(admin.getEmail());
        if (!m.matches()) {
            throw new ConsumerException("email不是一个合法的电子邮件地址");
        }
        //处理密码
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        admin.setPassword(encoder.encode(admin.getPassword()));
        Integer count = adminApi.update(admin);
        return count;
    }

    /**
     * 修改帐号状态
     *
     * @param id
     * @param status
     * @return
     */
    public Integer updateStatus(Integer id, Integer status) {
        UmsAdmin admin = new UmsAdmin();
        admin.setId(Convert.toLong(id));
        admin.setStatus(status);
        return adminApi.update(admin);
    }

    /**
     * 获取指定用户的角色
     *
     * @param adminId
     * @return
     */
    public List<UmsRole> role(Integer adminId) {
        List<UmsRole> result = new ArrayList<>();
        List<UmsAdminRoleRelation> relationList = adminRoleRelationApi.findByAdminId(Convert.toLong(adminId));
        if (ObjectUtil.isNull(relationList)) {
            return result;
        }

        for (UmsAdminRoleRelation relation : relationList) {
            UmsRole role = roleApi.findByRole(relation.getRoleId());
            if (StrUtil.equals(role.getName(), "超级管理员")) {
                result = roleApi.findAll();
                return result;
            } else {
                result.add(role);
            }
        }
        return result;
    }

    /**
     * 给用户分配角色
     *
     * @param adminId
     * @param roleIds
     * @return
     */
    public Integer updateRole(Integer adminId, Integer[] roleIds) {
        Integer count = 0;
        if (roleIds.length == 0) {
            adminRoleRelationApi.delete(adminId);
        }
        if (Arrays.asList(roleIds).contains(5)) {
            UmsAdminRoleRelation relation = new UmsAdminRoleRelation();
            relation.setAdminId(Convert.toLong(adminId));
            relation.setRoleId(5L);
            UmsAdminRoleRelation roleRelation = adminRoleRelationApi.find(adminId, 5);
            if (roleRelation == null) {
                adminRoleRelationApi.delete(adminId);
                count = adminRoleRelationApi.add(relation);
            }
            return count;
        } else {
            adminRoleRelationApi.delete(adminId);
            for (Integer roleId : roleIds) {
                UmsAdminRoleRelation relation = new UmsAdminRoleRelation();
                relation.setAdminId(Convert.toLong(adminId));
                relation.setRoleId(Convert.toLong(roleId));
                UmsAdminRoleRelation roleRelation = adminRoleRelationApi.find(adminId, roleId);
                if (roleRelation == null) {
                    adminRoleRelationApi.add(relation);
                }
                count++;
            }
            return count;
        }
    }
}
